let compare x = function
    y when x < y -> -1
  | y when x = y -> 0
  | _ -> 1

let rec add (x,y) l =
 let x2 = String.lowercase x in
match l with
  |[] -> (x,y)::[]
  | (e1,e2)::l when (compare x2 (String.lowercase e1)) < 0 -> (x,y)::(e1,e2)::l
  | (e1,e2)::l when (compare x2 (String.lowercase e1)) = 0 -> (e1,e2)::l
  | (e1,e2)::l -> (e1,e2)::(add (x,y) l)


let rec delete x = function
    [] -> []
  | (e1,e2)::l when (compare x e1) < 0 -> (e1,e2)::l
  | (e1,e2)::l when (compare x e1) = 0 -> l
  | (e1,e2)::l -> (e1,e2)::(delete x l)

let rec map f = function
    [] -> []
  | e::l -> (f e)::(map f l)

let sales l x =
  let f (a,b) = ((a,b-.((x/.100.)*.b)))
  in map f l

let rec update x y = function
    [] -> []
  | (e1,e2)::l when (compare x e1) < 0 -> (e1,e2)::l
  | (e1,e2)::l when (compare x e1) = 0 -> (e1,y)::l
  | (e1,e2)::l -> (e1,e2)::(update x y l)

let rec account x = function
    [] -> failwith "Client non existant"
  | (e1,e2)::_ when (compare x e1) < 0 -> failwith "Client non existant"
  | (e1,e2)::l when (compare x e1) = 0 -> e2
  | _::l -> account x l

let rec name x y l =
  let debt = account x l in
  let l1 = delete x l in
  add (y,debt) l1


let rec fusion = function
    (l,[]) | ([],l) -> l
  | ((e1,e2)::l,(h1,h2)::t) when (compare e1 h1) < 0 -> (e1,e2)::(fusion (l,(h1,h2)::t))
  | ((e1,e2)::l,(h1,h2)::t) when (compare e1 h1) = 0 -> (e1,e2+.h2)::(fusion (l,t))
  | ((e1,e2)::l,(h1,h2)::t) -> (h1,h2)::(fusion ((e1,e2)::l,t)) 


let rec divide = function
   [] -> ([], [])
  |[e] -> ([e],[])
  |e1::e2::l -> let (a, b) = (divide l) in
		  (e1::a, e2::b)

let rec merge = function
  ([],l)|(l,[]) -> l
  |(e1::l1,e2::l2) -> let (name1,_) = e1 and (name2,_) = e2 in
    if compare (String.lowercase name1) (String.lowercase name2) >= 0 then
      e2::(merge (e1::l1,l2))
    else
      e1::(merge (l1,e2::l2))

let rec merge_sort = function
   [] -> []
  |[e] -> [e]
  |l -> let (l1, l2) = divide l in
	merge (merge_sort l1, merge_sort l2)

let l = merge_sort [("Don",0.);("Nuts",1.);("Hai",3.);("Patates",4.);("Cuites",12.);("Jo",2.)]

let caesar n c = 
  if (c >= 'a' && c <= 'z') then
    print_char (char_of_int (((int_of_char c - 97 + (n mod 26)) mod 26) + 97))
  else if (c >= 'A' && c <= 'Z') then
    print_char (char_of_int (((int_of_char c - 65 + (n mod 26)) mod 26) + 65))
  else
    print_char c;;

let caesar_string n s =
  (* String.iter a le meme fonctionnement que List.iter *)
  String.iter (caesar n) s


let rec caesar_list n = function
   [] -> ()
  |(e1,e2)::l -> 
    begin
    caesar_string n e1;
    print_char '\n';
    caesar_list n l
  end

let rec revert_caesar_list n l = caesar_list (26 - n) l

let l = caesar_list 1 ["abcdEFGz\n", 2.]

let l2 = revert_caesar_list 1 ["bcdeFGHa\n", 2.]

let l = [("tOTo",543.);("ACDC",654.);("TeSt",543.);("Epita",543.)];;

caesar_list 1 l;;

let l = [("dYDy", 543.); ("KMNM", 654.); ("DoCd", 543.); ("Ozsdk", 543.)];;

revert_caesar_list 10 l;
